/******************************************************************/
/*                                                                */
/*  Winpooch : Windows Watchdog                                   */
/*  Copyright (C) 2004-2005  Benoit Blanchon                      */
/*                                                                */
/*  This program is free software; you can redistribute it        */
/*  and/or modify it under the terms of the GNU General Public    */
/*  License as published by the Free Software Foundation; either  */
/*  version 2 of the License, or (at your option) any later       */
/*  version.                                                      */
/*                                                                */
/*  This program is distributed in the hope that it will be       */
/*  useful, but WITHOUT ANY WARRANTY; without even the implied    */
/*  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR       */
/*  PURPOSE.  See the GNU General Public License for more         */
/*  details.                                                      */
/*                                                                */
/*  You should have received a copy of the GNU General Public     */
/*  License along with this program; if not, write to the Free    */
/*  Software Foundation, Inc.,                                    */
/*  675 Mass Ave, Cambridge, MA 02139, USA.                       */
/*                                                                */
/******************************************************************/


/******************************************************************/
/* Includes                                                       */
/******************************************************************/

// module's interface
#include "KeysWnd.h"

// standard headers
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <tchar.h>

// project's headers
#include "Assert.h"
#include "SpyDll.h"
#include "Trace.h"


/******************************************************************/
/* Internal constants                                             */
/******************************************************************/

// column identifiers
#define COL_KEYPATH	0
#define COL_HANDLES	1

// message to refresh list
#define WM_UPDATEKEYS	(WM_USER+20)

// window class name
#define WC_KEYSWND TEXT("KeysWnd")

#define MAX_KEYS	512


/******************************************************************/
/* Internal functions                                             */
/******************************************************************/

LRESULT CALLBACK _KeysWnd_WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ;


/******************************************************************/
/* Exported function : RegisterClass                              */
/******************************************************************/

BOOL KeysWnd_RegisterClass (HINSTANCE hInstance) 
{
  WNDCLASS wndclass ;

  wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  wndclass.lpfnWndProc   = _KeysWnd_WndProc ;
  wndclass.cbClsExtra    = 0 ;
  wndclass.cbWndExtra    = 0 ;
  wndclass.hInstance     = hInstance ;
  wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1) ;
  wndclass.lpszMenuName  = NULL ;
  wndclass.lpszClassName = WC_KEYSWND ;

  return 0!=RegisterClass (&wndclass) ;
}


/******************************************************************/
/* Exported function : CreateWindow                               */
/******************************************************************/

HWND KeysWnd_CreateWindow (HINSTANCE hInstance, HWND hwndParent)
{  
  return  CreateWindow (WC_KEYSWND, NULL,
			WS_CHILD,
			CW_USEDEFAULT, CW_USEDEFAULT,
			CW_USEDEFAULT, CW_USEDEFAULT, 
			hwndParent, NULL, hInstance, NULL) ;
}


/******************************************************************/
/* Internal function : WndProc                                    */
/******************************************************************/

LRESULT CALLBACK _KeysWnd_WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  static HWND		g_hwndList ;
  static HINSTANCE	g_hInstance ;

  int		nWidth ;
  int		nHeight ;
  LV_COLUMN	lvc ;

  union {
    NMHDR	*pnmh ;
    LV_KEYDOWN	*plvkd ;
  } nmu ;


  switch (message)
    {
    case WM_CREATE:
      
      g_hInstance = ((CREATESTRUCT*)lParam)->hInstance ;

      g_hwndList = CreateWindowEx (WS_EX_CLIENTEDGE, WC_LISTVIEW, NULL,
				  WS_CHILD|WS_VISIBLE|WS_VSCROLL|LVS_REPORT,
				  0,0,0,0, hwnd, NULL, g_hInstance, NULL) ;

      ASSERT  (g_hwndList!=NULL) ;
    
      // clear LVC struct
      ZeroMemory (&lvc, sizeof(lvc)) ;
      lvc.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM ;
      
      // add process name column
      lvc.cx = 300 ;
      lvc.iSubItem = COL_KEYPATH ;
      lvc.pszText = TEXT("Key") ;
      ListView_InsertColumn (g_hwndList, lvc.iSubItem, &lvc) ; 
      
      // add PID column
      lvc.cx = 40 ;
      lvc.iSubItem = COL_HANDLES ;
      lvc.pszText = TEXT("Handles") ;
      ListView_InsertColumn (g_hwndList, lvc.iSubItem, &lvc) ;   
	
      return 0 ; // case WM_CREATE:
      
    case WM_DESTROY:

      return 0 ;

    case WM_SHOWWINDOW:
      
      if( wParam ) // window is being shown
	PostMessage (hwnd, WM_UPDATEKEYS, 0, 0) ;

      return 0 ; // case WM_SHOWWINDOW:   

    case WM_SIZE:
      nWidth = LOWORD (lParam) ;
      nHeight = HIWORD (lParam) ;
      MoveWindow (g_hwndList, 0, 0, nWidth, nHeight, TRUE) ;
      return 0 ;

    case WM_UPDATEKEYS:
      {
       	REGKEYDESC aKeyDescs[MAX_KEYS] ;
	UINT nKeys, iKey ;

	nKeys = SpyDll_GetRegKeyList (aKeyDescs, MAX_KEYS) ;

	ListView_DeleteAllItems (g_hwndList) ;

	for( iKey=0 ; iKey<nKeys ; iKey++ )
	  {
	    TCHAR	szBuffer[16] ;
	    LVITEM	lvi = {0} ;

	    lvi.mask = LVIF_TEXT ;
	    lvi.iItem = iKey ;
	    lvi.iSubItem = COL_KEYPATH ;
	    lvi.pszText = aKeyDescs[iKey].szKey ;
	    ListView_InsertItem (g_hwndList, &lvi) ;

	    lvi.iSubItem = COL_HANDLES ;
	    lvi.pszText = szBuffer ;
	    wsprintf (szBuffer, TEXT("%u"), aKeyDescs[iKey].nHandles) ;
	    ListView_SetItem (g_hwndList, &lvi) ;
	  }
      }      
      return 0 ; // case WM_UPDATEKEYS:
      
    case WM_NOTIFY:
      
      nmu.pnmh = (NMHDR*) lParam ;

      if( nmu.pnmh->code==LVN_KEYDOWN &&
	  nmu.plvkd->wVKey==VK_F5 )
	{
	  PostMessage (hwnd, WM_UPDATEKEYS, 0, 0) ;
	  return 0 ;
	} // switch( LOWORD(wParam) )

      break  ; // case WM_NOTIFY:
    }

  return DefWindowProc (hwnd, message, wParam, lParam) ;
}
